moddbfandomcom-20200213-history
VBNET:ScriptingisthepastPart2
How to: Scripting is the past Native code is the future! Part 2 of 3 Author: Created by: X Web: http://www.createdbyx.com/ Date: December 2, 2004 The next code sample I will submit will be much more interesting, because it will demonstrate how the script and the application can communicate through an interface rather then the script having to use reflection to gain access to methods, classes and data inside of the application. The fallowing code is based on the previous code I provided and demonstrates how a script (Code that gets compiled) Can access public variables that are contained inside of the running application. The script does this using reflection. Note that I am specifying to compile the script to memory as well as not have the compiler generate any compiled assemblies. Simply create a new console application in vb.net and copy/paste the code below into the code window to run. The code is pretty self explanatory and easy enough to read through and understand. I hope this example app helps to inspire developers out there. 'Created by: X 'Copyright: Created by: X 'Web: http://www.createdbyx.com/ 'Date: January 28, 2004 ' Public Module General Public strTest As String = "Custom String" Public Sub Main() Dim Assm As System.Reflection.Assembly Dim Source As String Dim GenClass As Boolean = False ' change this to False to see different output ' build script code. Normally this would be done by loading a file containing the script code. Console.Write("Building script ...") Source = BuildScript(GenClass) Console.Write(" Done.") Console.WriteLine() ' now compile the script using codedom Console.Write("Compiling script ...") Assm = CompileScript(Source) If Not Assm Is Nothing Then Console.Write(" Done.") Console.WriteLine() Console.WriteLine("Running script ...") Console.WriteLine("---------------------------------------------------------") If GenClass Then Dim Obj As Object = Assm.CreateInstance("Test", True) ' we create the obj rather than getting it's type reference Dim Meth As Reflection.MethodInfo = Obj.GetType.GetMethod("TestIt") 'NOTE: You may need to specfy the owner of the method if the method is not declared shared. ' For example if System.Console.WriteLine was not a shared member you would need to ' specify Meth.Invoke(obj, Nothing). For example this code will cause an error ' Meth.Invoke(New CodeDom.CodeExpression(), Nothing) because the method does not belong to ' CodeDom.CodeExpression it belongs to Obj. Meth.Invoke(obj, Nothing) Else Dim Obj As Type = Assm.GetType("Test") ' get type reference for module Dim Meth As Reflection.MethodInfo = Obj.GetMethod("TestIt") 'NOTE: You may need to specfy the owner of the method if the method is not declared shared. ' For example if System.Console.WriteLine was not a shared member you would need to ' specify Meth.Invoke(obj, Nothing) Meth.Invoke(Nothing, Nothing) End If End If Console.WriteLine() Console.WriteLine("---------------------------------------------------------") Console.WriteLine("Press enter to quit...") Console.ReadLine() End Sub Public Function BuildScript(Optional ByVal GenerateClass As Boolean = True) As String Dim Source As String If GenerateClass Then Source = "Public Class Test" & vbCrLf Source &= "Public Sub TestIt()" & vbCrLf Source &= "System.Console.WriteLine(""Class code Worked!"")" & vbCrLf Source &= "End Sub" & vbCrLf Source &= "End Class" Else Source = "Public Module Test" & vbCrLf Source &= "Public Sub TestIt()" & vbCrLf Source &= "Dim S As String" & vbCrLf Source &= "Dim assm As System.Reflection.Assembly = System.Reflection.Assembly.GetCallingAssembly" & vbCrLf Source &= "System.Console.WriteLine( assm is nothing)" & vbCrLf Source &= "Dim T As System.Type" & vbCrLf Source &= " For Each T In assm.GetTypes()" & vbCrLf Source &= "System.Console.WriteLine(T.FullName)" & vbCrLf Source &= "Next" & vbCrLf Source &= "Dim Obj As System.Type = assm.GetType(""Scripting.General"") " & vbCrLf Source &= "System.Console.WriteLine( obj is nothing)" & vbCrLf Source &= "S = Obj.GetField(""strTest"").GetValue(Obj)" & vbCrLf Source &= "System.Console.WriteLine(""Module Code Worked! "" & S)" & vbCrLf Source &= "End Sub" & vbCrLf Source &= "End Module" End If Return Source End Function Public Function CompileScript(ByVal Source As String) As Reflection.Assembly Dim CodeP As New Microsoft.VisualBasic.VBCodeProvider() Dim Com As CodeDom.Compiler.ICodeCompiler Dim Param As New CodeDom.Compiler.CompilerParameters() Dim Ret As CodeDom.Compiler.CompilerResults ' we do not want to generate a file Param.GenerateExecutable = False Param.GenerateInMemory = True ' get a reference to the compiler Com = CodeP.CreateCompiler() ' Add the System.dll assembly so that the compiled script can write out to the console. Param.ReferencedAssemblies.Add("System.dll") ' Nopw we compile the script. Ret = Com.CompileAssemblyFromSource(Param, Source) ' If there were errors during compile tell user. If Ret.Errors.HasErrors Then Console.WriteLine() Console.WriteLine() Console.WriteLine(Ret.Errors.Item(0).ErrorText) Return Nothing End If Return Ret.CompiledAssembly End Function End Module